(function(_window,$){
    /**
     * 需要传入一个JQUERY对象，该对象将包裹所有的input或者待校验的输入域
      * @param validateTarget
     */
    _window.validator=function(option){
         var defaultOption={
             /**
              * 需要校验的输入域父级元素
              */
            validateTarget:undefined,
             /**
              * 是否或略隐藏的输入域，比如为hidden,display:none;
              */
            ignoreUnvisitable:false,
            errorOnfocus:false
        }
        this.option=this._extOption(option,defaultOption);
        this._init();
    }
    var validator = _window.validator;
    validator.prototype._registeValidator=function(elementName,targetElement,validator){
         if(!this.validatorRegistry){
             this.validatorRegistry={};
         }
        this.validatorRegistry[elementName]={targetElement:targetElement,validators:validator};
    }
    validator.prototype._extOption=function(option,defaultOption){
        for(var prop in defaultOption){
            option[prop]=option[prop]||defaultOption[prop];
        }
        return option;
    };
    validator.prototype._findEnterDomain=function(selector){
        return this.option.validateTarget.find(selector);
    }
    /**
     * 初始化
     * @private
     */
    validator.prototype._init=function(){
        var inputElements;
        var selectElements;
        var checkboxElements;
        var radioElements;
        var textareaElements;
        var validatorObject =this;
        if(this.option.ignoreUnvisitable){
            inputElements=this._findEnterDomain("input[type='text'][validator]:visible,input[validator]").filter(function(){
                var type = $(this).attr("type");
                return !type||type=='text'?true:false;
            });
            textareaElements= this._findEnterDomain("textarea[validator]:visible");
            checkboxElements= this._findEnterDomain("input[type='checkbox'][validator]:visible");
            radioElements=this._findEnterDomain("input[type='radio'][validator]:visible:checked");
            selectElements=this._findEnterDomain("select[validator]:visible");
        }else{
            inputElements=this._findEnterDomain("input[type='text'][validator],input[type='hidden'][validator],input[validator]").filter(function(){
                var type = $(this).attr("type");
                return !type||(type=='text'||type=='hidden')?true:false;
            });
            textareaElements= this._findEnterDomain("textarea[validator]");
            checkboxElements= this._findEnterDomain("input[type='checkbox'][validator]");
            radioElements=this._findEnterDomain("input[type='radio'][validator]:checked");
            selectElements=this._findEnterDomain("select[validator]");
        }
        inputElements.each(function(){
            var me = $(this);
            var validateType = me.attr("validator");
            if(!validateType){
                return ;
            }
            validatorObject._inputValidator(me);
        });
        textareaElements.each(function(){
            var me = $(this);
            var validateType = me.attr("validator");
            if(!validateType){
                return ;
            }
            validatorObject._textareaValidator(me);
        });
        selectElements.each(function(){
            var me = $(this);
            var validateType = me.attr("validator");
            if(!validateType){
                return ;
            }
            validatorObject._selectValidator(me);
        });
        radioElements.each(function(){
            var me = $(this);
            var validateType = me.attr("validator");
            if(!validateType){
                return ;
            }
            validatorObject._radioValidator(me);
        });
        var checkbox={};
        checkboxElements.each(function(){
            var me = $(this);
            var name = me.attr("name");
            if(!checkbox[name]){
                checkbox[name]=[];
            }
            checkbox[name].push(me.eq(0));
        });
        for(var name in checkbox){
            validatorObject._checkboxValidator(this._findEnterDomain("input[name='"+name+"'][type='checkbox']"));
        }
    }
    /**
     * 对外提供校验的入口方法
     */
    validator.prototype.validate=function(){
        var registry = this.validatorRegistry;
        if(!registry){
            throw(new Error("did not  found any element for validate!"));
        }
        for(var key in registry){
            var validRes=false;
            var validatorResult;
            if(!registry[key]){
                continue;
            }
           var target = this.option.validateTarget.find("[name='"+key+"']");
           var or = target.attr("or");
           var validators=[registry[key]];
           if(or&& $.trim(or)!=""){
              var ors = or.split(",");
              for(var i=0;i<ors.length;i++){
                  var orValidator =  registry[ors[i]];
                  validators.push(orValidator);
                  //如果是or条件判断，则将已经参与校验的移除校验注册表
                  registry[ors[i]]=undefined;
              }
            }
            for(var i=0;i<validators.length;i++){
                var tempValidRes=true;
                var valid = validators[i];
                var validatorFns = valid.validators;
                for(var j=0;j<validatorFns.length;j++){
                    var result = validatorFns[j](valid.targetElement,this);
                    tempValidRes=tempValidRes&&result.result;
                    if(!tempValidRes){
                        validatorResult= result;
                    }
                }
                validRes=validRes||tempValidRes;
            }
            if(!validRes){
                if(this.option.errorOnfocus){
                validators[0].targetElement.focus();
                }
                return validatorResult;
            }
        }
        return this._createValidateResult(true);
    };
    validator.prototype._wrapValidator=function(element){
        var validateType = element.attr("validator");
        var elementName = element.attr("name");
        this._registeValidator(elementName,element,this._generateValidator(validateType));
    };
    validator.prototype._generateValidator=function(validateType){
        var validators = [];
        if(!validateType|| $.trim(validateType)==""){
            return validators;
        }
        var types = validateType.split(",");
        for(var i=0;i<types.length;i++){
            validators.push(this._validatorFactory[types[i]]);
        }
        return validators;
    };
    /**
     * 对input类型参数进行校验
     * @param element
     * @private
     */
    validator.prototype._inputValidator=function(element){
        this._wrapValidator(element);
    };
    /**
     * 对select类型的输入域进行校验
     * @param element
     * @private
     */
    validator.prototype._selectValidator=function(element){
       this._wrapValidator(element);
    };
    /**
     * 对textarea类型进行校验
     * @param element
     * @private
     */
    validator.prototype._textareaValidator=function(element){
       this._wrapValidator(element);
    };
    /**
     * 对checkbox类型的输入域进行校验
     * @param element
     * @private
     */
    validator.prototype._checkboxValidator=function(elements){
        elements.attr("validator","checkbox");
        this._wrapValidator(elements);
    };

    /**
     * 对radio类型的输入域进行校验
     * @param element
     * @private
     */
    validator.prototype._radioValidator=function(element){
       this._wrapValidator(element);
    };
    validator.prototype._createValidateResult=function(result,tip){
        return {result:result,tip:tip};
    };
    validator.prototype._parseInt=function(str,defaultVal){
        var INT_PATTERN = /([0-9]{1})|([1-9][0-9]{0,})/;
        if(!str|| $.trim(str)==''){
            return defaultVal;
        }else if(INT_PATTERN.test(str)){
            return parseInt(str);
        }else{
            return parseInt($(str).val());
        }
    };
    validator.prototype._validatorFactory={
        /**
         *空值校验
         */
        empty:function(element,validatorObj){
            var val = element.val();
            var tip=element.attr("tip");
            if(!val|| $.trim(val)==""){
                return validatorObj._createValidateResult(false,tip);
            }
            return validatorObj._createValidateResult(true);
        },
        /**
         * 正则表达式校验
         * @param element
         */
        regex:function(element,validatorObj){
                var val = element.val();
                var tip = element.attr("tip");
                var regex=element.attr("regex");
                if(!regex|| $.trim(regex)==""){
                    return validatorObj._createValidateResult(true);
                }
                var regex = new RegExp(regex);
                if(regex.test(val)){
                    return validatorObj._createValidateResult(true);
                }else{
                    return validatorObj._createValidateResult(false,tip);
                }
        },
        /**
         * 数字校验
         * @param element
         */
        number:function(element,validatorObj){
            var val = element.val();
            var max = element.attr("max");
            var min = element.attr("min");
            var tip = element.attr("tip");
            var scale = element.attr("scale");
            max=validatorObj._parseInt(max,2147483647);
            min=validatorObj._parseInt(min,-2147483648);
            scale=validatorObj._parseInt(scale,2147483647);

           var patternStr = "([0-9]{1}[\.]{0,1}[0-9]{0,"+scale+"})|([1-9]{1}[0-9]{0,}[\.]{0,1}[0-9]{0,"+scale+"})"
            var NUMBER_PATTERN=new RegExp(patternStr);
            if(val&&$.trim(val)!=""){
                if(NUMBER_PATTERN.test(val)){
                    val = parseFloat(val);
                    if(val>=min&&val<=max){
                        return  validatorObj._createValidateResult(true);
                    }
                    return validatorObj._createValidateResult(false,tip);
                }else{
                    return validatorObj._createValidateResult(false,tip);
                }
            }else{
                return validatorObj._createValidateResult(true);
            }
        },
        /**
         * 长度校验
         * @param element
         */
        length:function(element,validatorObj){
            var val = element.val();
            var max = element.attr("max");
            var min = element.attr("min");
            var tip = element.attr("tip");
            max=validatorObj._parseInt(max,2147483647);
            min=validatorObj._parseInt(min,-2147483648);
            if(val&&$.trim(val)!=""){
                var length = val.length;
                if(length>=min&&length<=max){
                    return validatorObj._createValidateResult(true);
                }else{
                    return validatorObj._createValidateResult(false,tip);
                }
            }else{
                return validatorObj._createValidateResult(false,tip);
            }

        },
        json:function(element,validatorObj){
            var val = element.val();
            var tip = element.attr("tip");
            if(!val|| $.trim(val)==""){
                return validatorObj._createValidateResult(true);
            }
            try{
                $.json(val);
                return validatorObj._createValidateResult(true);
            }catch(e){
                return validatorObj._createValidateResult(false,tip);
            }
        },
        checkbox:function(element,validatorObj){
            var checkedSize =  element.filter(":checked").length;
            var max = element.attr("max");
            var min = element.attr("min");
            var tip = element.attr("tip");
            max=validatorObj._parseInt(max,2147483647);
            min=validatorObj._parseInt(min,-2147483648);
            if(checkedSize>=min&&checkedSize<=max){
                return validatorObj._createValidateResult(true);
            }
            return validatorObj._createValidateResult(false,tip);
        }
    };

})(window,$);